home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
oper_sys
/
emerald
/
emrldsys.lha
/
Language
/
Compiler
/
knowCT.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-16
|
19KB
|
677 lines
/*
* @(#)knowCT.c 1.6 3/13/89
*/
#include "assert.h"
#include "nodes.h"
#include "map.h"
#include "sequence.h"
#include "trace.h"
#include "semantics.h"
#include "builtins.h"
#include "primitives.h"
#include "MyParser.h"
#include "flags.h"
extern NodePtr getCTInfo();
Map nodeToStruct;
extern Map manifestMap;
/*
* Handling of invoc nodes.
* Stage 0: ignore them
* Stage 1: only depend on CT of target
* Stage 2: depend on CT of target and args, and propogate CT information
* the args to results of the operation.
*/
#define STAGE1
static void CT_addDependent(parent, child)
NodePtr parent, child;
{
NodePtr childStruct;
NodePtr parentStruct;
parentStruct = (NodePtr) Map_Lookup(nodeToStruct, (int)parent);
if ((int)parentStruct == NIL) {
parentStruct = Construct(P_KNOWCT, 3, NN, NN, NN);
parentStruct->b.knowct.tag = parent->tag;
parentStruct->b.knowct.definingThing = parent;
Map_Insert(nodeToStruct, (int)parent, (int)parentStruct);
}
childStruct = (NodePtr) Map_Lookup(nodeToStruct, (int)child);
if ((int)childStruct == NIL) {
childStruct = Construct(P_KNOWCT, 3, NN, NN, NN);
childStruct->b.knowct.tag = child->tag;
childStruct->b.knowct.definingThing = child;
Map_Insert(nodeToStruct, (int)child, (int)childStruct);
}
Sequence_Add(&parentStruct->b.knowct.dependsOn, childStruct);
}
extern void resolveGlobal();
static void CT_TryToAddDependent(parent, child)
NodePtr parent, child;
{
Symbol st;
switch (parent->tag) {
case P_SYMBOL:
st = (Symbol) parent;
if (st->isManifest) {
CT_addDependent(parent, Construct(T_NONE, 0));
return;
}
break;
case P_INVOC:
if (Map_Lookup(manifestMap, (int)parent) != NIL) {
CT_addDependent(parent, Construct(T_NONE, 0));
return;
}
default:
break;
}
switch (child->tag) {
case P_GLOBALREF:
resolveGlobal(child, (ValuePtr)NULL);
assert(child->b.globalref.value != NN);
CT_addDependent(parent, child->b.globalref.value);
break;
case T_NONE:
case P_INVOC:
case P_VECTORLIT:
case P_BOOLLIT:
case P_CHARLIT:
case P_INTLIT:
case P_REALLIT:
case P_STRINGLIT:
case P_BUILTINLIT:
case P_SELFLIT:
case P_ATLIT:
case P_OBLIT:
case P_NTHRESULT:
case P_EXP:
case P_UNARYEXP:
CT_addDependent(parent, child);
break;
case P_SYMREF:
case P_SYMDEF:
CT_addDependent(parent, (NodePtr) child->b.symref.symbol);
break;
case P_SYMBOL:
CT_addDependent(parent, child);
break;
default:
CT_addDependent(parent, Construct(T_NONE, 0));
break;
}
}
/*ARGSUSED*/
static void addResultSymbols(p, ob)
NodePtr p, ob;
{
#ifdef JUNKKKK
NodePtr q, r;
assert(p->tag == P_OPDEF);
assert(ob->tag == P_OBLIT);
q = p->b.opdef.sig->b.opsig.results;
Sequence_For(r, q)
assert(r->tag == P_PARAM);
assert(r->b.param.sym->tag == P_SYMDEF);
CT_TryToAddDependent(ob, (NodePtr)r->b.param.sym->b.symdef.symbol);
Sequence_Next
#endif
}
extern NodePtr findObjectOperation(), OTLookup();
void buildKnowCTGraph(p)
register NodePtr p;
{
register NodePtr q, right, left, nth;
if ((int)p <= 0x200) return;
switch (p->tag) {
case P_ASSIGNSTAT:
right = p->b.assignstat.right;
left = p->b.assignstat.left;
if (Sequence_Length(right) > 1) {
/* is a multiple assignment */
Sequence_For(q, left)
assert(q->tag == P_SYMREF);
CT_TryToAddDependent((NodePtr)q->b.symref.symbol,
right->b.children[z__z]);
Sequence_Next
} else if (Sequence_Length(left) == 1) {
q = left->b.children[0];
assert(q->tag == P_SYMREF);
CT_TryToAddDependent((NodePtr)q->b.symref.symbol, right->b.children[0]);
} else {
Sequence_For(q, left)
assert(q->tag == P_SYMREF);
nth = Construct(P_NTHRESULT, 0);
nth->b.nthresult.whichResult = z__z;
CT_TryToAddDependent(nth, right->b.children[0]);
CT_TryToAddDependent((NodePtr)q->b.symref.symbol, nth);
Sequence_Next
}
break;
case P_INVOC:
if ((q = (NodePtr)Map_Lookup(manifestMap, (int)p + 2)) != (NodePtr)NIL) {
return;
}
#ifdef STAGE0
/* do not do anything */
#else
#ifdef STAGE1
CT_TryToAddDependent(p, p->b.invoc.target);
if (p->b.invoc.target->tag == P_SYMREF &&
p->b.invoc.target->b.symref.symbol->isManifest) {
NodePtr ct, opdef, results;
Symbol st;
ct = p->b.invoc.target->b.symref.symbol->value.CTinfo;
if (ct == NULL) {
TRACE2(knowct, 9, "CT of manifest symbol (0x%08x %s) is null",
p->b.invoc.target->b.symref.symbol,
ST_SymbolName(p->b.invoc.target->b.symref.symbol));
} else {
TRACE1(knowct, 9, "CT of invoc target is manifest (0x%08x)", ct);
opdef = findObjectOperation(ct, p->b.invoc.opname);
assert(opdef != NULL);
results = opdef->b.opdef.sig->b.opsig.results;
if (Sequence_Length(results) == 1) {
st = results->b.children[0]->b.param.sym->b.symdef.symbol;
TRACE2(knowct, 9, "The result symbol is \"%s\"(0x%08x)",
ST_SymbolName(st), st);
TRACE0(knowct, 9, "Adding result symbol as dependent of invoc");
CT_TryToAddDependent(p, (NodePtr)st);
}
}
}
#else
#ifdef STAGE2
Sequence_For(q, p->b.invoc.args)
assert(q->tag == P_ARG);
q = q->b.arg.exp;
CT_TryToAddDependent(p, q);
Sequence_Next
#endif
#endif
#endif
break;
case P_CONSTDECL:
if (p->b.constdecl.sym->b.symdef.symbol->isManifest) {
CT_TryToAddDependent((NodePtr) p->b.constdecl.sym->b.symdef.symbol,
p->b.constdecl.sym->b.symdef.symbol->value.value);
break;
}
case P_VARDECL:
if (p->b.constdecl.value != NN)
CT_TryToAddDependent((NodePtr) p->b.constdecl.sym->b.symdef.symbol,
p->b.constdecl.value);
break;
case P_PARAM:
break;
case P_UNARYEXP:
break;
case P_EXP:
break;
case P_ATLIT:
case P_OBLIT:
CT_TryToAddDependent((NodePtr)p->b.oblit.name->b.symdef.symbol, p);
Sequence_For(q, p->b.oblit.setq)
assert(q->b.setq.inner->tag == P_SYMDEF);
CT_TryToAddDependent((NodePtr) q->b.setq.inner->b.symdef.symbol,
(NodePtr) q->b.setq.outer);
Sequence_Next
if (p->tag == P_OBLIT) {
Sequence_For(q, p->b.oblit.ops)
addResultSymbols(q, p);
Sequence_Next
if (p->b.oblit.monitor != NN) {
Sequence_For(q, p->b.oblit.monitor->b.monitor.ops)
addResultSymbols(q, p);
Sequence_Next
}
}
break;
case P_IMPORT:
break;
case P_EXPORT:
break;
case P_PRIMSTAT:
if (Sequence_Length(p->b.primstat.vars) <= 0) break;
if (p->b.primstat.number->tag == P_STRINGLIT) {
CT_TryToAddDependent((NodePtr)p->b.primstat.vars->b.children[0]->b.symref.symbol,
Construct(T_NONE, 0));
} else {
int pNum;
PrimitiveDescPtr pdp;
pNum = atoi(p->b.primstat.number->b.intlit.string);
for (pdp = primitives; pdp->number != 0 && pdp->number != pNum; pdp++) ;
assert(pdp->number != 0);
assert(pdp->isFunction);
if (pdp->atindex[0] == ANYINDEX) {
CT_TryToAddDependent((NodePtr)p->b.primstat.vars->b.children[0]->b.symref.symbol,
Construct(T_NONE, 0));
} else {
CT_TryToAddDependent((NodePtr)p->b.primstat.vars->b.children[0]->b.symref.symbol,
refToBuiltin(B_INSTCT, (int)pdp->atindex[0]));
}
}
break;
default:
break;
}
Sequence_For(q, p)
if ((int)q > 0x200) buildKnowCTGraph(q);
Sequence_Next
}
void initializeKnowCT()
{
nodeToStruct = Map_Create();
}
static char *thingName(t)
NodePtr t;
{
static char buffer[128];
if (t->b.knowct.tag == P_SYMBOL) sprintf(buffer, "Symbol %s (0x%08x)",
ST_SymbolName((Symbol)(t->b.knowct.definingThing)), t->b.knowct.definingThing);
else sprintf(buffer, "%s (0x%08x) on line %d", tagNames[(int)t->b.knowct.tag],
t->b.knowct.definingThing, t->b.knowct.definingThing->lineNumber);
return(buffer);
}
extern void findAll();
void displayKnowCTGraph()
{
NodePtr thing, theStruct, q;
IFTRACE(knowct, 5) {
Map_For(nodeToStruct, thing, theStruct)
printf("struct 0x%08x %s", theStruct, thingName(theStruct));
if (theStruct->b.knowct.isDone) printf(" isDone");
if (theStruct->b.knowct.isOK) printf(" isOK");
printf(" depends on:\n");
Sequence_For(q, theStruct->b.knowct.dependsOn)
printf("\t\tstruct 0x%08x %s\n", q, thingName(q));
Sequence_Next
Map_Next
}
}
Boolean isSameCT(a, b)
NodePtr a, b;
{
if (a->tag == P_ATLIT) {
assert(a->b.atlit.f.cannotBeConformedTo);
a = OTLookup(a->b.atlit.codeOID);
}
if (b->tag == P_ATLIT) {
assert(b->b.atlit.f.cannotBeConformedTo);
b = OTLookup(b->b.atlit.codeOID);
}
a = GETVALUE(a);
b = GETVALUE(b);
assert(a->tag == P_OBLIT && b->tag == P_OBLIT);
return(a->b.oblit.codeOID == b->b.oblit.codeOID);
}
void propagateCTInfo(p)
NodePtr p;
{
NodePtr q, ct = NULL, oldCT, opdef, aSymbolStruct;
register Symbol st;
Boolean areAllSymbols = TRUE, foundFirstCT, foundDependent;
if (p->tag == T_SEQUENCE) {
TRACE0(knowct, 3, "Trying to progagate to a set");
Sequence_For(q, p)
assert(q->tag == P_KNOWCT);
if (q->b.knowct.tag != P_SYMBOL) {
if (areAllSymbols) TRACE0(knowct, 3, "The set contains non-symbols");
TRACE1(knowct, 5, "%s", thingName(q));
areAllSymbols = FALSE;
}
Sequence_Next
if (areAllSymbols) {
TRACE0(knowct, 3, "The set contains only symbols, so trying harder");
foundFirstCT = FALSE;
foundDependent = FALSE;
Sequence_For(aSymbolStruct, p)
TRACE2(knowct, 4, "Looking at pre-reqs of 0x%08x %s", aSymbolStruct,
thingName(aSymbolStruct));
Sequence_For(q, aSymbolStruct->b.knowct.dependsOn)
TRACE2(knowct, 5, "Looking at 0x%08x %s", q, thingName(q));
assert(q->tag == P_KNOWCT);
if (! q->b.knowct.isDone) continue; /* it is in this set */
foundDependent = TRUE;
if (!q->b.knowct.isOK) {
TRACE2(knowct, 5, "0x%08x %s not ok, give up", q, thingName(q));
ct = NULL;
break;
}
if (!foundFirstCT) {
ct = q->b.knowct.answer;
foundFirstCT = TRUE;
} else {
if (! isSameCT(ct, q->b.knowct.answer)) {
TRACE4(knowct, 5, "CT of 0x%08x %s (0x%08x) != 0x%08x, give up", q,
thingName(q), q->b.knowct.answer, ct);
ct = NULL;
break;
}
}
Sequence_Next
Sequence_Next
if (! foundDependent) {
TRACE1(knowct, 3, "Symbol %s has no dependents", thingName(p));
ct = NULL;
}
}
Sequence_For(aSymbolStruct, p)
if (ct != NULL) {
oldCT = ((Symbol)aSymbolStruct->b.knowct.definingThing)->value.CTinfo;
if (oldCT != NN) assert(isSameCT(oldCT, ct));
((Symbol)aSymbolStruct->b.knowct.definingThing)->value.CTinfo = ct;
}
aSymbolStruct->b.knowct.isDone = TRUE;
aSymbolStruct->b.knowct.isOK = (ct != NULL);
aSymbolStruct->b.knowct.answer = ct;
TRACE4(knowct, 1, "Finalizing 0x%08x %s: %s 0x%08x", aSymbolStruct,
thingName(aSymbolStruct),
aSymbolStruct->b.knowct.isOK ? "know CT" : "do not know CT",
aSymbolStruct->b.knowct.answer);
Sequence_Next
return;
}
assert(p->tag == P_KNOWCT);
TRACE2(knowct, 3, "Propagating 0x%08x %s", p, thingName(p));
switch (p->b.knowct.tag) {
case T_NONE:
ct = NN;
break;
case P_INVOC:
#ifdef STAGE0
/* do nothing */
ct = NULL;
#else
#ifdef STAGE1
p->b.knowct.answer = (NodePtr) Map_Lookup(manifestMap,
(int)p->b.knowct.definingThing + 1);
if ((int)p->b.knowct.answer != NIL) {
p->b.knowct.isDone = TRUE;
p->b.knowct.isOK = TRUE;
TRACE4(knowct, 1, "Finalizing (manifest) 0x%08x %s: %s 0x%08x", p, thingName(p),
p->b.knowct.isOK ? "know CT" : "know CT",
p->b.knowct.answer);
return;
}
q = p->b.knowct.dependsOn->b.children[0];
TRACE2(knowct, 4, "Looking at 0x%08x %s", q, thingName(q));
assert(q->tag == P_KNOWCT);
assert(q->b.knowct.isDone);
ct = NULL;
if (!q->b.knowct.isOK) {
TRACE2(knowct, 5, "0x%08x %s not ok, give up", q, thingName(q));
} else {
ct = q->b.knowct.answer;
TRACE3(knowct, 5, "0x%08x %s ok, ct = 0x%08x", q, thingName(q), ct);
opdef = findObjectOperation(ct, p->b.knowct.definingThing->b.invoc.opname);
assert(opdef != NULL);
q = opdef->b.opdef.sig->b.opsig.results;
if (Sequence_Length(q) == 1) {
st = q->b.children[0]->b.param.sym->b.symdef.symbol;
TRACE2(knowct, 5, "The result symbol is \"%s\"(0x%08x)",
ST_SymbolName(st), st);
ct = getCTInfo(st);
} else {
ct = NULL;
}
}
#else
#ifdef STAGE2
Sequence_For(q, p->b.knowct.dependsOn)
TRACE2(knowct, 4, "Looking at 0x%08x %s", q, thingName(q));
assert(q->tag == P_KNOWCT);
assert(q->b.knowct.isDone);
if (!q->b.knowct.isOK) {
TRACE2(knowct, 5, "0x%08x %s not ok, give up", q, thingName(q));
ct = NULL;
break;
}
Sequence_Next
ct = NULL;
#endif
#endif
#endif
break;
case P_NTHRESULT:
#ifdef STAGE0
/* do nothing */
ct = NULL;
#else
#ifdef STAGE1
assert(Sequence_Length(p->b.knowct.dependsOn) == 1);
q = p->b.knowct.dependsOn->b.children[0];
/* q now points to a P_INVOC struct */
assert(q->b.knowct.tag == P_INVOC);
assert(q->b.knowct.isDone);
assert(Sequence_Length(q->b.knowct.dependsOn) == 1);
q = p->b.knowct.dependsOn->b.children[0];
/* q now points to a the struct for the target */
TRACE2(knowct, 4, "Looking at 0x%08x %s", q, thingName(q));
assert(q->tag == P_KNOWCT);
assert(q->b.knowct.isDone);
ct = NULL;
if (!q->b.knowct.isOK) {
TRACE2(knowct, 5, "0x%08x %s not ok, give up", q, thingName(q));
} else {
ct = q->b.knowct.answer;
TRACE3(knowct, 5, "0x%08x %s ok, ct = 0x%08x", q, thingName(q), ct);
opdef = findObjectOperation(ct, p->b.knowct.definingThing->b.invoc.opname);
assert(opdef != NULL);
q = opdef->b.opdef.sig->b.opsig.results;
assert(Sequence_Length(q) > p->b.nthresult.whichResult);
st = q->b.children[p->b.nthresult.whichResult]->b.param.sym->b.symdef.symbol;
TRACE1(knowct, 5, "The result symbol is \"%s\"", ST_SymbolName(st));
ct = getCTInfo(st);
}
#else
#ifdef STAGE2
Sequence_For(q, p->b.knowct.dependsOn)
TRACE2(knowct, 4, "Looking at 0x%08x %s", q, thingName(q));
assert(q->tag == P_KNOWCT);
assert(q->b.knowct.isDone);
if (!q->b.knowct.isOK) {
TRACE2(knowct, 5, "0x%08x %s not ok, give up", q, thingName(q));
ct = NULL;
break;
}
Sequence_Next
ct = NULL;
#endif
#endif
#endif
break;
case P_EXP:
switch (p->b.knowct.definingThing->b.exp.op) {
case KAND:
case KOR:
case OIDENTITY:
case ONOTIDENTITY:
case OCONFORMSTO:
ct = refToBuiltin(B_INSTCT, BOOLEANINDEX);
break;
default:
assert(FALSE);
break;
}
break;
case P_UNARYEXP:
switch (p->b.knowct.definingThing->b.unaryexp.op) {
case KISFIXED:
case KAWAITING:
ct = refToBuiltin(B_INSTCT, BOOLEANINDEX);
break;
case KLOCATE:
ct = refToBuiltin(B_INSTCT, NODEINDEX);
break;
default:
assert(FALSE);
break;
}
break;
case P_VECTORLIT:
ct = findInstCode(p->b.knowct.definingThing->b.vectorlit.vectorType);
break;
case P_BOOLLIT:
ct = refToBuiltin(B_INSTCT, BOOLEANINDEX);
break;
case P_CHARLIT:
ct = refToBuiltin(B_INSTCT, CHARACTERINDEX);
break;
case P_INTLIT:
ct = refToBuiltin(B_INSTCT, INTEGERINDEX);
break;
case P_REALLIT:
ct = refToBuiltin(B_INSTCT, REALINDEX);
break;
case P_STRINGLIT:
ct = refToBuiltin(B_INSTCT, STRINGINDEX);
break;
case P_BUILTINLIT:
ct = refToBuiltinFromToken(B_IT,
p->b.knowct.definingThing->b.builtinlit.whichType);
break;
case P_SELFLIT:
assert(FALSE);
break;
case P_ATLIT:
ct = refToBuiltin(B_INSTCT, SIGNATUREINDEX);
break;
case P_OBLIT:
ct = p->b.knowct.definingThing;
break;
case P_SYMBOL:
st = (Symbol) p->b.knowct.definingThing;
if (st->isManifest) {
p->b.knowct.isDone = TRUE;
p->b.knowct.isOK = TRUE;
p->b.knowct.answer = st->value.CTinfo;
TRACE4(knowct, 1, "Finalizing (manifest) 0x%08x %s: %s 0x%08x", p,
thingName(p),
p->b.knowct.isOK ? "know CT" : "know CT",
p->b.knowct.answer);
return;
}
foundFirstCT = FALSE;
Sequence_For(q, p->b.knowct.dependsOn)
TRACE2(knowct, 3, "Looking at 0x%08x %s", q, thingName(q));
assert(q->tag == P_KNOWCT);
assert(q->b.knowct.isDone);
if (!q->b.knowct.isOK) {
TRACE2(knowct, 5, "0x%08x %s not ok, give up", q, thingName(q));
ct = NULL;
break;
}
if (!foundFirstCT) {
ct = q->b.knowct.answer;
foundFirstCT = TRUE;
} else {
if (! isSameCT(ct, q->b.knowct.answer)) {
TRACE4(knowct, 4, "CT of 0x%08x %s (0x%08x) != 0x%08x, give up", q,
thingName(q), q->b.knowct.answer, ct);
ct = NULL;
break;
}
}
Sequence_Next
if (! foundFirstCT) {
TRACE1(knowct, 3, "Symbol %s has no dependents", thingName(p));
ct = NULL;
}
if (ct != NULL) {
oldCT = ((Symbol)p->b.knowct.definingThing)->value.CTinfo;
if (!bflag && oldCT != NN) assert(isSameCT(oldCT, ct));
((Symbol)p->b.knowct.definingThing)->value.CTinfo = ct;
}
break;
default:
break;
}
p->b.knowct.isDone = TRUE;
p->b.knowct.isOK = (ct != NULL);
p->b.knowct.answer = ct;
TRACE4(knowct, 1, "Finalizing 0x%08x %s: %s 0x%08x", p, thingName(p),
p->b.knowct.isOK ? "know CT" : "do not know CT",
p->b.knowct.answer);
}
static int count = 0;
static NodePtr SCstack = NULL;
static NodePtr SCComponent = NULL;
#define min(A, B) ((A) < (B) ? (A) : (B))
void SearchC(v)
register NodePtr v;
{
register NodePtr x, w;
v->b.knowct.marked = TRUE;
v->b.knowct.number = count++;
v->b.knowct.lowLink = v->b.knowct.number;
Sequence_Add(&SCstack, v);
v->b.knowct.onStack = TRUE;
Sequence_For(w, v->b.knowct.dependsOn)
if (! w->b.knowct.marked) {
SearchC(w);
v->b.knowct.lowLink = min(v->b.knowct.lowLink, w->b.knowct.lowLink);
} else {
if (w->b.knowct.number < v->b.knowct.number && w->b.knowct.onStack) {
v->b.knowct.lowLink = min(w->b.knowct.number, v->b.knowct.lowLink);
}
}
Sequence_Next
if (v->b.knowct.lowLink == v->b.knowct.number) {
TRACE0(knowct, 1, "------");
Sequence_ReverseFor(x, SCstack)
SCstack->nChildren --;
assert(x->b.knowct.onStack);
x->b.knowct.onStack = FALSE;
if (SCComponent == NULL && x == v) {
/* this is the only element of the component */
SCComponent = x;
} else {
Sequence_Add(&SCComponent, x);
}
TRACE2(knowct, 2, "struct 0x%08x %s", x, thingName(x));
if (x == v) break;
Sequence_Next
propagateCTInfo(SCComponent);
if (SCComponent->tag == T_SEQUENCE) {
free((char *)SCComponent);
}
SCComponent = NULL;
}
}
void FindAll()
{
NodePtr theThing, theStruct;
Map_For(nodeToStruct, theThing, theStruct)
if (! theStruct->b.knowct.marked) SearchC(theStruct);
Map_Next
}
void doKnowCTs(p)
NodePtr p;
{
buildKnowCTGraph(p);
displayKnowCTGraph();
FindAll();
}